﻿#pragma once
#ifndef _CALIBRATIONPROCESS_H_
#define _CALIBRATIONPROCESS_H_

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video.hpp>
#include <opencv2/opencv.hpp>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include </usr/include/eigen3/Eigen/Dense>
#include <vector>
#include <fstream>

//要采集的图片个数
#define COLLECTNUM 25
//对采集到的原来的图像标定
#define ORIGPICTURE 0
//对矫正完的图像进行标定
#define CORRPICTURE 1

class CalibrationProcess {
public:
	/* 函数 : 声明以及初始化一些变量和对象 //主要是因为在回调函数里面啧啧，我想把图片作为输入，emmmm//
     *
     *@参数  :  无
     */
	void Init();

	/* 函数 : 写一个总的采集标定的程序，在里面调用采集和标定的功能函数 //主要是因为在回调函数里面啧啧，我想把图片作为输入，emmmm//
	 *
	 *@参数  :  (Mat)picture
	 *@返回  :  是否标定完成的标志 true 或 false
	 */
	bool CollectCalibration(cv::Mat picture);

	/* 函数 : 根据设定的时间采集标定图片 
	 *
	 *@参数  :  (Mat)picture
	 *@返回  :  无
	 */
	void CollectPicture(cv::Mat picture);


	/* 函数   ：对采集到的图片进行标定，得到内外参矩阵，畸变系数矩阵，都是全局变量
     *  
     * @参数  ：因为两次标定会得到两组数值信息，参数是告诉函数该用哪一组的数据
     */
	void CalibrationPicture(std::vector<cv::Mat> &pictures,int picflag);

	/* 函数名 ：计算映射矩阵H
     *  
     * @参数：求第几幅图像的H
     * @返回值：H矩阵
     */
	Eigen::MatrixXd CalculateHmatrix(int imageNum, int picflag);

	/* 函数  ： 对采集到的图片进行矫正
	 *
	 * @参数：需要矫正的原图
	 * @返回值：矫正好的图片
	*/
	cv::Mat CorrectPicture(cv::Mat frame, bool display);

	/* 函数名：对图像坐标进行映射，得到对应的世界坐标系坐标
     *  
     * @参数：（Xc,Yc）图像坐标
     * @返回值：（Xw,Yw）世界坐标
     */
	cv::Point2d TableMap(float X, float Y, Eigen::MatrixXd hmatrix);

	/* 函数名：对图像坐标进行映射，得到对应的世界坐标系坐标
     *  
     * @参数：（Xc,Yc）图像坐标
     * @返回值：（Xw,Yw）世界坐标
     */
    std::vector<double> PixelMapWorld(std::vector<double>& Pixel, int picturetime);

	/* 函数 : 计时器功能
     *
     *@参数  :  
     */
	static void*  TimeCount(void* args);

	/* 函数 : restart
     * @目的 ： 采集的图片如果不满意，则清零相关参数，重新进行采集
     * @返回值： 无
     */
	void restart();

	/////////////////////////////////////////////////////////////////////
	/*帮助我测试的函数们*/

	/* 函数名：testResult
	 * @目的： 验算结果
	 * @参数：0 为验算原图像的映射误差 1 为验算矫正图像的映射误差
	 * @返回值：无
	*/
	void testResult(int picflag);

	/* 函数名：GetCorpictures
	 * @目的： 矫正输入的一组图片
	 * @参数：pictures 需要矫正的一组图片 corrpictures 矫正完的一组图片
	 * @返回值：无
	*/
	void GetCorpictures();//帮助得到矫正的图片

	/* 函数名：coutH
	 * @目的： 输出H矩阵
	 * @参数：HMatrix 要打印的H矩阵
	 * @返回值：无
	*/
	void coutH(Eigen::MatrixXd HMatrix);





private:
	//采集的15幅图片
	std::vector<cv::Mat> Pictures;
	//矫正完用于第二次标定的图片
	std::vector<cv::Mat> CorPictures;
	//对应内角点的棋盘实际位置坐标
	std::vector<std::vector<cv::Point3f>> object_points;
	//对应的内角点坐标
	std::vector<std::vector<cv::Point2f>> image_points_seq;
	//由像素坐标映射到实际坐标的一组系数
	double a1;
	double a2;
	double a3;
	double a4;
	double a5;
	double a6;
	//保存每幅图像的旋转矩阵
	cv::Mat Romatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));
	//在保存图片的时候按名称保存用到
	int croNum = 0;
	std::string imageFileName;
	std::string filePath;
	std::stringstream StrStm;
	//设定的隔几秒采集一次
	int intervaltime = 5;
	//只执行一次的标志
	int exetime = 0;

	int pointnum;

	//线程是否创建成功：0
	int ret;
	//开始进行标定
	int startCalibration = 0;
	//角点坐标
	std::vector<cv::Point2f> image_points_buf;
    //因为进行了两组图片的角点提取，每一组图片都有可能有的提取不到角点，所以定义个二维数组来分别存储可提取到角点的图片数量
    std::vector<std::vector <int> > correctPoint;

};

#endif
